﻿using SourceMaster.Util;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SourceMaster.Model
{
    public class MyCommit
    {
        
        public string AuthorEmail { get; set; }
        public string AuthorName { get; set; }
        public DateTime Date { get; set; }
        public string Description { get; set; }
        public string ShortDescription { get; set; }

        public List<string> DisplayTags { get; set; }
        public ObservableCollection<MyTag> Tags { get; set; }

        public string Hash { get; set; }
        
        public List<MyBranch> Branches { get; set; }
        public List<MyBranch> BranchesAround { get; set; }

        public List<string> ParentHashes { get; set; }
        public int ParentCount { get; set; }
        public List<MyCommit> Parents { get; set; }

        public int VisualPosition { get; set; }
        public bool IsHead { get; set; }
        public List<MyCommit> Children { get; set; }

        public LibGit2Sharp.ObjectId ObjectId { get; set; }

        // origin commit
        public LibGit2Sharp.Commit originCommit { get; set; }

        public string FormattedDate
        {
            get
            {
                return DateUtil.GetRelative(Date);
            }
        }

        public string HashShort
        {
            get
            {
                return Hash.Substring(0, 7);
            }
        }

        public string Author
        {
            get
            {
                return AuthorName + " <" + AuthorEmail + ">";
            }
        }

        public bool IsMergeCommit()
        {
            return ParentCount > 1;
        }

        public static MyCommit Create(LibGit2Sharp.Repository repo,
            LibGit2Sharp.Commit commit, ObservableCollection<MyTag> myTags)
        {
            var c = new MyCommit();

            // 
            var myCommitTags = new ObservableCollection<MyTag>();
            foreach(var myTag in myTags)
            {
                if(myTag.TargetSha == commit.Sha)
                {
                    myCommitTags.Add(myTag);
                    myTag.Target = c;
                }
            }

            var displayTags = new List<string>();
            if (repo.Head.Tip == commit)
                displayTags.Add("HEAD");

            var parentHashes = new List<string>();
            foreach(var parentCommit in commit.Parents)
            {
                parentHashes.Add(parentCommit.Sha);
            }

            c.AuthorEmail = commit.Author.Email;
            c.AuthorName = commit.Author.Name;
            c.Date = commit.Author.When.DateTime;
            c.Description = commit.Message;
            c.ShortDescription = commit.Message.Right(72).Replace("\n", "").Replace("\r", "");
            c.DisplayTags = displayTags;
            c.Branches = new List<MyBranch>();
            c.Tags = myCommitTags;
            c.Hash = commit.Sha;
            c.ParentHashes = parentHashes;
            c.ParentCount = commit.Parents.Count();
            c.Parents = new List<MyCommit>();
            c.ObjectId = commit.Id;
            c.VisualPosition = -1;   // the number will be used when draw the graph
            c.Children = new List<MyCommit>();

            c.originCommit = commit;

            return c;
        }

        // set up the parent object relationship
        public void PostProcess(ObservableCollection<MyCommit> myCommits, ObservableCollection<MyBranch> myBranches)
        {
            // Set Parents
            if(ParentCount > 0)
            {
                foreach(string hash in ParentHashes)
                {
                    MyCommit parentCommit = myCommits.Where(c => c.Hash == hash).FirstOrDefault();
                    if(parentCommit != null)
                    {
                        Parents.Add(parentCommit);
                        parentCommit.Children.Add(this);
                    }
                }
            }
            
            // Set BranchesAround
            BranchesAround = RepoUtil.GetBranchesAroundCommit(this, myBranches);
        }
    }
}
